package com.mdp.tpa.pay.wxpay.ctrl;

import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mdp.core.entity.Result;
import com.mdp.core.entity.Tips;
import com.mdp.core.err.BizException;
import com.mdp.core.utils.*;
import com.mdp.safe.client.entity.User;
import com.mdp.safe.client.utils.LoginUtils;
import com.mdp.tpa.client.service.AppTpPayService;
import com.mdp.tpa.pay.cm.entity.MiniAppUniOrder;
import com.mdp.tpa.pay.cm.entity.Orders;
import com.mdp.tpa.pay.cm.client.AcPaymentPushService;
import com.mdp.tpa.pay.cm.service.OrdersService;
import com.mdp.tpa.pay.wxpay.service.WxpayPubService;
import com.mdp.tpa.wechat.api.PayService;
import com.mdp.tpa.wechat.wxpaysdk.WXPayConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

@RestController("tpa.pay.wxpayJsapiController")
@RequestMapping(value="/**/pay/wxpay")
public class WxpayJsapiController {

	private Logger logger= LoggerFactory.getLogger(WxpayJsapiController.class);

	@Autowired
	WxpayPubService  wxpayPubService;

	ObjectMapper objectMapper=new ObjectMapper();

	@Autowired
	WXPayConfig config;

	@Autowired
	private OrdersService ordersService;


	
	@Autowired
	private AppTpPayService appTpPayService;

	@Autowired
	private PayService payService;


	@Autowired
	AcPaymentPushService acPaymentPushService;

	/**
	 * 调用微信的统一下单接口，生成预支付交易单
	 * 微信支付要求：除被扫支付场景以外，商户系统先调用该接口在微信支付服务后台生成预支付交易单，返回正确的预支付交易回话标识后再按扫码、JSAPI、APP等不同场景生成交易串调起支付

	 */
	@RequestMapping(value="/uniOrder/jsapi",method=RequestMethod.POST)
	public Result uniOrder(@RequestBody MiniAppUniOrder order) {
		String outTradeNo=order.getId();
		Map<String,Object> result=new HashMap<String,Object>(); 
		Map<String,Object> data=new HashMap<String,Object>(); 

		 Tips tips=new Tips("下单成功");
			User user= LoginUtils.getCurrentUserInfo();
			if(LoginUtils.isGuest()){
				return Result.error("user-not-exists-or-nologin","用户不存在或未登录，无法下单！");
			}
		String openid=order.getPayOpenid();
		if(!StringUtils.hasText(openid) && !StringUtils.hasText(user.getTpaOpenid())){
			return Result.error("payOpenid-0","请切换回微信登录后再支付");
		}
		logger.debug("收到客户端上送订单消息：订单号：" + order.getId() );
		Orders orders = ordersService.getOrders(order);
		try {
			if(orders==null){
				return Result.error("orders-is-not-exists","订单不存在");
			}else if(!orders.getUserid().equals(user.getUserid())){
				return Result.error("orders-is-not-yours","订单不属于您的");
			}else if("3".equals(orders.getOrderStatus())||"1".equals(orders.getPayStatus())){
				return Result.error("orders-had-pay","订单已支付");
			}else if(!"0".equals(orders.getPayStatus())){
				return Result.error("orders-not-in-pay","订单暂未需要支付");
			}else  if(orders.getPayAt()==null || orders.getPayAt().compareTo(BigDecimal.ZERO)<=0){
				throw new BizException("WxPayService74", "orderAmount", "付款金额不正确，必须大于0元");
			}

			config.setNotifyUrl(config.getNotifyUrl());
			String body=orders.getName();
			JSONObject attach=new JSONObject();
			attach.put("otype",orders.getOtype());
			String payId= UUID.randomUUID().toString();
			attach.put("payId", payId);
  			String spbillCreateIp=RequestUtils.getIpAddr(RequestUtils.getRequest());
			data=payService.unifiedOrder(config,outTradeNo,body,attach.toJSONString(),spbillCreateIp,wxpayPubService.DTI100(orders.getPayAt()),"", openid);
 			//更新订单preId
			Orders ordersUpdate=new Orders(orders.getId());
			ordersUpdate.setOtype(order.getOtype());
			ordersUpdate.setPrepayId((String) data.get("prepay_id"));
			ordersUpdate.setPrepayTime(new Date());
			ordersUpdate.setPayId(payId);
			ordersUpdate.setPayType("1");
			ordersService.updatePrepayId(ordersUpdate);

			Map<String,Object> pushOrders=BaseUtils.toMap(orders);
			pushOrders.put("action","createOrder");
			pushOrders.put("ip",spbillCreateIp);
			pushOrders.put("payId",ordersUpdate.getPayId());
			pushOrders.put("prepayId",ordersUpdate.getPrepayId());
			pushOrders.put("prepayTime",ordersUpdate.getPrepayTime());
			pushOrders.put("otype",orders.getOtype());
			pushOrders.put("payOpenid",openid);
			pushOrders.put("payType",ordersUpdate.getPayType());
			if("5".equals(orders.getOtype())){
				acPaymentPushService.pushRechargeOrders(pushOrders );
			}else{
				acPaymentPushService.pushPaymentOrders(pushOrders );
			}
			return Result.ok();

		} catch (BizException e) {
			logger.error("执行异常",e);
			return Result.error(e);
		}catch (Exception e) {
			logger.error("执行异常",e);
			return Result.error(e.getMessage());
		}
	}

	/**
	 * 微信支付后结果通知
	 *
	 * <xml><appid><![CDATA[wx3d57ec32bf63d5fa]]></appid>
	 <attach><![CDATA[1]]></attach>
	 <bank_type><![CDATA[CFT]]></bank_type>
	 <cash_fee><![CDATA[100]]></cash_fee>
	 <fee_type><![CDATA[CNY]]></fee_type>
	 <is_subscribe><![CDATA[N]]></is_subscribe>
	 <mch_id><![CDATA[1389170202]]></mch_id>
	 <nonce_str><![CDATA[WNOMdeCUh0B8Yd5R]]></nonce_str>
	 <openid><![CDATA[oBi4O0ZO-JL1Ey_s9kWcQBmg3NwY]]></openid>
	 <out_trade_no><![CDATA[qrH64u8YvpS]]></out_trade_no>
	 <result_code><![CDATA[SUCCESS]]></result_code>
	 <return_code><![CDATA[SUCCESS]]></return_code>
	 <sign><![CDATA[19CC706B8C07D8B9E2E770E0DB634D03]]></sign>
	 <time_end><![CDATA[20170808155031]]></time_end>
	 <total_fee>100</total_fee>
	 <trade_type><![CDATA[JSAPI]]></trade_type>
	 <transaction_id><![CDATA[4000802001201708085155314485]]></transaction_id>
	 </xml>
	 * @param context
	 * @param request
	 * @param response
	 */
	@RequestMapping(value="/notify/jsapi",method=RequestMethod.POST)
	public void notify(@RequestBody String context, HttpServletRequest request, HttpServletResponse response) {
		Map<String,Object> order =new HashMap<String,Object>();
		String resultStr="<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
		try {
			try {
				response.setContentType("text/xml");
				response.getWriter().write(resultStr);
			} catch (IOException e1) {

			}
			order= XmlUtils.string2Map(context);
			String outTradeNo=(String) order.get("out_trade_no");
			String feeType=(String) order.get("fee_type");
			String tranId=(String) order.get("transaction_id");
			String openid=(String) order.get("openid");
			String gsn=(String) order.get("out_trade_no");
			String bankType=(String) order.get("bank_type");
			String sign=(String) order.get("sign");
			String resultCode=(String) order.get("result_code");
			String returnCode=(String) order.get("return_code");
			String totalFee=(String) order.get("total_fee");


			if(!"SUCCESS".equals(resultCode)){
				return  ;
			}
			Map<String,Object> map=new HashMap<String,Object>();
			Tips tips=new Tips("下单成功");
			String distinctKey="notify"+sign;
			if(!DistinctUtil.isDistinct(distinctKey)){
				logger.warn("微信支付结果通知重复过滤");
				return  ;
			}
			String attachStr=(String) order.get("attach");
			JSONObject attach=JSONObject.parseObject(attachStr);


			String otype= (String) attach.get("otype");
			String payId= (String) attach.get("payId");
			String payAuthId= (String) attach.get("payAuthId");

			try {
				logger.debug("收到客户端上送订单消息：订单号："+outTradeNo+"，订单详细描述："+attach+"，数量：未知，单价：未知，otype:"+otype+"微信订单号："+tranId+"，opendid"+openid);
 				ordersService.payConfirm(otype,outTradeNo,payId,tranId, NumberUtil.getBigDecimal(totalFee),"");

			} catch (BizException e) {
				DistinctUtil.remove(distinctKey);
				logger.error("执行异常",e);
				tips=e.getTips();
			}catch (Exception e) {
				DistinctUtil.remove(distinctKey);
				logger.error("执行异常",e);
			}

			return  ;
		}   catch (Exception e) {
			logger.error("执行异常",e);
		}

	}
	@PostConstruct
	public void initObjectMapper(){
		objectMapper.setSerializationInclusion(com.fasterxml.jackson.annotation.JsonInclude.Include.ALWAYS);
		objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
		objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true);

	}

}
